#ifndef WAYPOINTLIST_H
#define WAYPOINTLIST_H

#include <QList>
#include <QDateTime>
#include <QMutex>
#include "waypoint.h"
#include "../FsxWsUtils/jsonmarkuphelper.h"

class FsxSimConnect::Waypoint; // forward declaration due to cross dependencies

namespace FsxSimConnect {

//! List of waypoints.
/*! \author KWB */
class WaypointList : public QList<Waypoint>
{
private:
    mutable QMutex _mutex; /*!< Mutex for thread safety */
    //! Waypoints to a KML track.
    /*! \param level indention level */
    QString toKmlTrack (const int level) const;
    //! Waypoints to a KML look at element.
    /*! \param level indention level
        \param lastWaypoints use only last n waypoints for calculation */
    QString toKmlLookAt(const int level, const int lastWaypoints) const;
    //! Deep copy of the waypoints.
    /*! \param otherWaypoints waypoints to copy */
    void initByOtherWaypoints(const WaypointList &otherWaypoints);
public:
    //! Default constructor.
    WaypointList();
    //! Copy constructor, init by other waypoints (deep copy)
    /*! \param otherWaypoints */
    WaypointList(const WaypointList &otherWaypoints);
    //! Assigment operator.
    /*! \param otherWaypointList
        \return assigned list */
    WaypointList &operator =(const WaypointList &otherWaypointList); // assignment operator
    //! Update Instrumentation data if within time frame, otherwise append.
    /*! \param data instrumentation data, speed data
        \param timeFrameMs timeframe (since now) in ms, -1 force append
        \sa FSXAircraftInstrumentationData
        \sa FSXAircraftPositionAndSpeedData
        \returns updated or just created waypoint */
    template <class DATASTRUCT> Waypoint updateOrAppend(const DATASTRUCT &data, qint64 timeFrameMs);
    //! Average value of the last waypoints.
    /*! \param numberLastWaypoints number of waypoints (at the end) consodered
        \param actualCount number of waypoints really considered for average, e.g. if count()<numberLastWaypoints */
    Waypoint average(const int numberLastWaypoints, int &actualCount) const;
    //! Update the deltas if this list represents delta values.
    /*! \param waypoints List on which this delta list is based on
        \param fullBuild rebuild the whole list or just append at the end */
    void updateDeltas(const WaypointList &waypoints, bool fullBuild = false);
    //! JSON array waypoint representation of the list.
    /*! \param level indention level
        \param resolutionPeriodMs resolution of waypoints [ms] */
    QString toJsonArray(const int level = 0, const qint64 resolutionPeriodMs = -1) const;
    //! KML waypoint representation of the list.
    /*! \param level indention level
        \param parameter KML parameters */
    QString toKml(const int level, const KmlParameter &parameter) const;
    //! Reduce to a maximum of waypoints.
    /*! Remove the oldest waypoints (at the beginning) so a maximum of
        values is in the list
        \param maxNumber max. elements in the list
        \returns number of elements removed, 0 if nothing has been removed */
    int reduce(const int maxNumber);
    //! Waypoint (index) since given timestamp.
    /*! \param timestamp search for index >= timestamp
        \returns index of first waypoint newer/equal to timestamp or <0 if not found */
    int waypointsSince(const qint64 timestamp);
    //! List will only contain newer (equal) waypoints.
    /*! \param timestampUtcEpoch remove older elements
        \returns number of elements removed, 0 if nothing has been removed */
    int reduceToNewerOrEqual(const qint64 timestampUtcEpoch);
    //! List will only contain waypoints within x ms from the last waypoint.
    /*! \param timeframeMs starting from last waypoint's timestamp
        \returns number of elements removed, 0 if nothing has been removed */
    int reduceToNewerOrEqualRelative(const qint64 timeframeMs);
    //! Waypoints with reduced (slower) resolution.
    /*! \param resolutionMs next waypoint will be at least this time later
        \return reduced waypoints list */
    WaypointList reducedResolution(const qint64 resolutionMs) const;
};

} // namespace

#endif // WAYPOINTLIST_H
